import { FC, useEffect, useState } from 'react'
import styles from './FineMachining.module.scss'
import { useColorVar, useStyles } from '@/hooks/styles'
import { ViewTitle } from '@/components/universal/ViewTitle/ViewTitle'
import { MainGraph } from '@/components/3FineMachining/MainGraph'
import { BlockTitle } from '@/components/universal/BlockTitle/BlockTitle'
import { ImageItemForTest } from '@/components/1RoughMachining/ImageList'
import { useGenStore, useGraphStore, useRoughStore } from '@/hooks'
import { observer } from 'mobx-react'
import { Button, Image, message, Spin, Tooltip, Upload } from 'antd'
import {
  CaretRightOutlined,
  Loading3QuartersOutlined,
  LoadingOutlined,
  UploadOutlined,
} from '@ant-design/icons'
import { ScaleLines } from '@/components/3FineMachining/ScaleLines'
import { Node } from '@antv/x6'
import { baseUrl, motionEasing, token, uploadUrl } from '@/config'
import { motion } from 'framer-motion'
import { SvgIcon } from '@/components/icons'
import { IconAxisArrow, IconTest } from '@/components/icons/IconStyleFactory'
import { calcSortPos, ImageNode } from '@/components/3FineMachining/ImageNode'
import axios from 'axios'
import { posScale } from '@/components/3FineMachining/utils'

export const FineMachining: FC = observer(() => {
  const c = useColorVar()
  const styleClass = useStyles(styles)
  const [messageApi, contextHolder] = message.useMessage()
  const rough = useRoughStore()
  const graphStore = useGraphStore()
  const genStore = useGenStore()

  const [previewGenLoading, setPreviewGenLoading] = useState<boolean>(false)

  const handleIteration = async () => {
    const imageNodes = graphStore.graph.getNodes()
    const imageInAxis = [] as { id: string; weight: number }[] // 用户排序的图片对象列表
    const image_list = [] as string[] // 轴中的图片（接口输入）
    const weight = [] as number[] // 轴中图片的坐标
    const target_image_list = [] as string[] // 待排序的图片列表（接口输入）

    for (let i = 0; i < imageNodes.length; i++) {
      if (imageNodes[i].id !== 'mark') {
        if (imageNodes[i].getData()['inTrack'] === false) {
          target_image_list.push(imageNodes[i].id)
        } else {
          imageInAxis.push({
            id: imageNodes[i].id,
            weight: calcSortPos(imageNodes[i].position().x) / 100,
          })
        }
      }
    }

    if (imageInAxis.length !== 0) {
      imageInAxis.sort((a, b) => a.weight - b.weight)
      imageInAxis.map((item) => {
        image_list.push(item.id)
        weight.push(item.weight)
      })

      console.log({ image_list, weight, target_image_list })

      messageApi.loading({
        key: '2',
        content: 'Processing',
        duration: 15,
      })
      await axios
        .post(`${baseUrl}/rough/sort`, {
          image_list,
          weight,
          target_image_list,
        })
        .then((res) => {
          console.log(res.data.data)
          const resultPos = res.data.data as number[]
          calcPos(imageNodes, target_image_list, posScale(resultPos))
          messageApi.success({ key: '2', content: 'Sorting completed' })
          return
        })
        .catch((error) => {
          messageApi.error({ key: '2', content: 'Sorting failed' })
          console.log('error', error)
          return
        })
    }
  }

  const calcPos = (
    imageNodes: Node[],
    target_image_list: string[],
    resultPos: number[]
  ) => {
    const lineSize = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
    target_image_list.map((imageNodeID, index) => {
      const imageNode = imageNodes.find((item) => item.id === imageNodeID)
      const lie = Math.floor(resultPos[index] * 10) // 第几列
      const hang = lineSize[lie] // 第几行
      if (hang <= 6) {
        imageNode.translate(
          72 + lie * 104 - imageNode.position().x,
          278 + 81 * hang - imageNode.position().y,
          { transition: { duration: 750, timing: 'easeInOutCubic' } } // 动画选项
        )
        imageNode.setPosition({ x: 72 + lie * 104, y: 278 + 81 * hang })
        imageNode.setData(
          {
            position: { x: 72 + lie * 104, y: 278 + 81 * hang },
          },
          { deep: false, silent: true }
        ) // 浅merge,不触发重绘
      } else {
        imageNode.translate(
          72 + lie * 104 - imageNode.position().x,
          278 + 81 * 10 - imageNode.position().y,
          { transition: { duration: 750, timing: 'easeInOutCubic' } } // 动画选项
        )
        imageNode.setPosition({ x: 72 + lie * 104, y: 278 + 81 * 10 })
        imageNode.setData(
          {
            position: { x: 72 + lie * 104, y: 278 + 81 * 10 },
          },
          { deep: false, silent: true }
        ) // 浅merge,不触发重绘
      }
      lineSize[lie] += 1
    })
  }

  const image2image = async () => {
    const currentStyle = rough.styleList.filter(
      (style) => style.id === rough.currentStyleID
    )[0]
    setPreviewGenLoading(true)
    // messageApi.loading({ key: 'i2i', content: 'Generating...', duration: 30 })
    await axios
      .post(`${baseUrl}/fine/generate`, {
        description: '', // 此处description是提示词，不是风格描述
        image_list: currentStyle.image_list,
        weight: 0.95, // 风格的渲染程度
        weight_list: currentStyle.weight,
        target_weight: [0, 0.08, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.92, 1],
        batch_size: 1, // 每一个目标风格强度的生成数量
        num_each_bath: 10,
        image: graphStore.testImage,
        denoising_strength: 0.7, // 原图的修改程度
        guidanceScale: 7.5,
        num_inference_steps: 30, // 采样步骤
      })
      .then((res) => {
        // console.log(res.data.data)
        const result = []
        for (let i = 0; i < res.data.data.length; i++) {
          result.push(res.data.data[i][0]['url'])
        }
        graphStore.setPreviewImage(result)
        setPreviewGenLoading(false)
        // messageApi.success({ key: 'i2i', content: 'Done!' })
        return
      })
      .catch((error) => {
        setPreviewGenLoading(false)
        // messageApi.error({ key: 'i2i', content: 'Error!' })
        console.log('error', error)
        return
      })
  }

  const saveStyle = async (ifNew: boolean) => {
    const temp = []
    const imageInAxis = [] as { id: string; weight: number }[] // 用户排序的图片对象列表
    const image_list = [] as string[] // 轴中的图片（接口输入）
    const weight = [] as number[] // 轴中图片的坐标
    const imageNodes = graphStore.graph.getNodes()

    imageNodes.map((item, index) => {
      if (item.id === 'mark') {
        return
      }
      const itemData = item.getData()
      temp.push({
        id: item.id,
        url: itemData.url,
        position: [item.position().x, item.position().y],
        data: itemData,
      })
      if (item.getData()['inTrack']) {
        imageInAxis.push({
          id: item.id,
          weight: calcSortPos(item.position().x) / 100,
        })
      }
    })
    if (imageInAxis.length >= 2) {
      imageInAxis.sort((a, b) => a.weight - b.weight)
      imageInAxis.map((item) => {
        image_list.push(item.id)
        weight.push(item.weight)
      })
    } else {
      // 如果轴中的图片小于两张
      messageApi.info({
        key: 'save',
        content: 'Please place at least two images in the axis!',
      })
      return
    }

    // console.log(image_list, weight, temp)
    const postData = {
      id: ifNew ? null : rough.currentStyleID,
      image_list: image_list,
      weight: weight,
      data: {
        description: rough.description,
        references: rough.reference,
        weight: Number(rough.weight[1].toFixed(2)),
        testImage: graphStore.testImage,
        previewImageList: graphStore.previewImageList,
        canvasImageList: temp,
        mode: genStore.mode,
        applyStyle: genStore.applyStyle,
        strength: genStore.strength,
        positivePrompt: genStore.positivePrompt,
        negativePrompt: genStore.negativePrompt,
        renderLevel: genStore.renderLevel,
        originalImage: genStore.originalImage,
        modificationLevel: genStore.modificationLevel,
        generatedImage: genStore.generatedImage,
      },
    }
    await axios
      .post(`${baseUrl}/library/save`, { ...postData })
      .then((res) => {
        // console.log(res.data.data) ，返回新建该style的id
        if (rough.currentStyleID === null || ifNew) {
          // 如果是新建style，则store中保存该style，或者点击的是back按钮
          rough.addStyle({ ...postData, id: res.data.data as string })
          rough.setCurrentStyleID(res.data.data as string) // 设置当前所在编辑的styleID
        } else {
          // 如果是已有style的覆盖编辑，则store中做替换
          rough.replaceStyle({ ...postData })
        }
        messageApi.success({ key: 'save', content: 'Saved!' })
        return
      })
      .catch((error) => {
        messageApi.error({ key: 'save', content: 'Error' })
        console.log('error', error)
      })
  }

  return (
    <div {...styleClass(['layout'])}>
      {contextHolder}
      <ViewTitle text={'Fine Machining'} {...styleClass(['title'])} />
      <div {...styleClass(['test'])}>
        <div {...styleClass(['test-upper'])}>
          <div {...styleClass(['test-upper-title'])}>
            <BlockTitle
              title={'Test List'}
              icon={<SvgIcon icon={IconTest} />}
            />
            <div {...styleClass(['test-upper-title-desc'])}>
              Upload an image to see the transitions in different style
              strengths
            </div>
          </div>
          <div {...styleClass(['test-upper-upload'])}>
            <ImageItemForTest
              url={
                graphStore.testImage === ''
                  ? rough.reference[0]
                  : graphStore.testImage
              }
              index={999}
              onDelete={() => graphStore.deleteTestImage()}
            />
            <div {...styleClass(['test-upper-upload-right'])}>
              <Upload
                accept="image/*"
                headers={{ Authorization: token }}
                action={uploadUrl}
                onChange={(file) => {
                  if ('response' in file.file) {
                    const url = file.file.response.data as string
                    graphStore.setTestImage(url)
                  }
                }}
              >
                <Button
                  // icon={<UploadOutlined rev={null} />}
                  {...styleClass(['test-upper-upload-right-button'])}
                >
                  <div {...styleClass(['test-upper-upload-right-button-text'])}>
                    <UploadOutlined rev={null} style={{ marginRight: 8 }} />
                    Upload
                  </div>
                </Button>
              </Upload>
              <Button
                // icon={<UploadOutlined rev={null} />}
                {...styleClass(['test-upper-upload-right-button'])}
                onClick={() => image2image()}
              >
                <div {...styleClass(['test-upper-upload-right-button-text'])}>
                  {previewGenLoading ? (
                    <LoadingOutlined rev={null} style={{ marginRight: 8 }} />
                  ) : (
                    <Loading3QuartersOutlined
                      rev={null}
                      style={{ marginRight: 8 }}
                    />
                  )}
                  Refresh
                </div>
              </Button>
            </div>
          </div>
        </div>

        <div {...styleClass(['test-low-wrapper'])}>
          <div {...styleClass(['test-low-sider'], { left: 0 })}></div>
          <div {...styleClass(['test-low-sider'], { right: 0 })}></div>
          <div {...styleClass(['test-footer'])}>
            <div {...styleClass(['test-footer-temp'])}></div>
            {graphStore.previewImageList.map((item, index) => (
              <div
                key={`${item}-${index}`}
                {...styleClass(['test-footer-img-wrapper'], {
                  background: previewGenLoading
                    ? `rgba(0,0,0,${0.02 + index * 0.008})`
                    : 'rgba(0,0,0,0)',
                })}
              >
                {previewGenLoading ? (
                  <Spin
                    indicator={
                      <LoadingOutlined
                        style={{ fontSize: 24 }}
                        spin
                        rev={'zmx'}
                      />
                    }
                  />
                ) : (
                  <Image
                    src={item}
                    width={68}
                    height={68}
                    placeholder={
                      <Image
                        src={`${item}?x-oss-process=image/blur,r_50,s_50/quality,q_1/resize,m_mfit,h_68,w_68`}
                        width={68}
                        height={68}
                        preview={false}
                        draggable={false}
                      />
                    }
                  />
                )}
              </div>
            ))}
            <div {...styleClass(['test-footer-temp'])}></div>
          </div>
          <div {...styleClass(['test-down-layout'])}>
            {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((item) => (
              <div key={item} {...styleClass(['test-down-block'])}>
                <div {...styleClass(['test-down-shu'])}></div>
              </div>
            ))}
            <div {...styleClass(['test-down-heng'])}></div>
            <div {...styleClass(['test-down-arrow'])}>
              <CaretRightOutlined
                rev={null}
                {...styleClass([], { color: c('axis') })}
              />
            </div>
          </div>
        </div>
      </div>

      <div {...styleClass(['button-group'])}>
        <div {...styleClass(['button-group-upper'])}>
          <Tooltip title={'train and reorder'}>
            <Button
              {...styleClass(['test-upper-upload-button-text'])}
              onClick={() => handleIteration()}
            >
              Confirm
            </Button>
          </Tooltip>
          <Tooltip title={'save copy as'}>
            <Button
              {...styleClass(['test-upper-upload-button-text'])}
              onClick={() => saveStyle(true)}
            >
              Back
            </Button>
          </Tooltip>
        </div>

        <Tooltip title={'overwrite the style'}>
          <Button
            {...styleClass(['button-group-button2'])}
            onClick={() => saveStyle(false)}
          >
            <div {...styleClass(['button-group-text'], { color: '#AD9F67' })}>
              Save
            </div>
          </Button>
        </Tooltip>
      </div>

      <div {...styleClass(['axis-title'])}>
        <div {...styleClass(['axis-title-text'])}>
          ———— Style Strength Axis ————
        </div>
      </div>

      <MainGraph />
    </div>
  )
})

interface IGraphMark {
  node?: Node
}
export const GraphMark: FC<IGraphMark> = observer(({ node }) => {
  const c = useColorVar()
  const styleClass = useStyles(styles)
  const graphStore = useGraphStore()

  useEffect(() => {
    if (graphStore.imageInTrackMark) {
      setTimeout(() => graphStore.setImageInTrackMark(false), 400)
    }
  }, [graphStore.imageInTrackMark])
  return (
    <div {...styleClass(['mark'])}>
      <ScaleLines />
      <motion.div
        {...styleClass(['mark-track'])}
        animate={{
          borderColor: graphStore.imageInTrackMark ? c('light') : '#C3B3AB',
          scaleY: graphStore.imageInTrackMark ? 1.08 : 1,
          background: graphStore.imageInTrackMark
            ? 'rgba(197,188,152,0)'
            : 'rgba(197,188,152,0.2)',
        }}
        transition={{ ...motionEasing, duration: 0.4 }}
      ></motion.div>
    </div>
  )
})
